import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSInterfaceChild;
import com.speljohan.rsbot.table.AbstractTreeTableModel;
import com.speljohan.rsbot.table.JTreeTable;

public class InterfaceExplorer extends Script {

	private class HighlightInterface implements ListSelectionListener,
			PaintListener {
		private Object select;

		@SuppressWarnings("deprecation")
		HighlightInterface() {
			Bot.getEventManager().addListener(PaintListener.class, this);
		}

		public void onRepaint(final Graphics render) {
			if (select instanceof RSInterfaceChild) {
				final RSInterfaceChild inter = (RSInterfaceChild) select;
				if (inter.isValid()) {
					final Rectangle rect = inter.getArea();
					render.setColor(Color.ORANGE);
					render.drawRect(rect.x, rect.y, rect.width, rect.height);
				}
			}
		}

		public void valueChanged(final ListSelectionEvent e) {
			final int selected = table.getSelectedRow();
			if (selected != -1) {
				select = table.getTree().getPathForRow(selected)
						.getLastPathComponent();
			} else {
				select = null;
			}
		}
	}

	private static class InterfaceModel extends AbstractTreeTableModel {
		private final String[] cNames = new String[] { "Index", "Action",
				"Type", "ModelID", "TextureID", "Text", "Actions", "Inventory" };

		private final List<RSInterface> inters = new ArrayList<RSInterface>();

		String search = "";

		public InterfaceModel() {
			super(null);
			root = this;
		}

		public Object getChild(final Object node, final int index) {
			if (node instanceof InterfaceModel) {
				return inters.get(index);
			}
			if (node instanceof RSInterface) {
				final RSInterface n = (RSInterface) node;
				return n.getChild(index);
			}
			return null;
		}

		public int getChildCount(final Object node) {
			if (node instanceof InterfaceModel) {
				return inters.size();
			}
			if (node instanceof RSInterface) {
				final RSInterface n = (RSInterface) node;
				return n.getChildCount();
			}
			return 0;
		}

		public int getColumnCount() {
			return cNames.length;
		}

		public String getColumnName(final int column) {
			return cNames[column];
		}

		public Object getValueAt(final Object node, final int column) {
			if (node instanceof InterfaceModel) {
				return column == 0 ? "Root" : "";
			}
			if (node instanceof RSInterface) {
				final RSInterface n = (RSInterface) node;
				return column == 0 ? "[" + n.getIndex() + "]" : "";
			}
			if (node instanceof RSInterfaceChild) {
				final RSInterfaceChild n = (RSInterfaceChild) node;
				switch (column) {
				case 0:
					return "[" + n.getIndex() + "]";
				case 1:
					return n.getActionType();
				case 2:
					return n.getType();
				case 3:
					return n.getModelID();
				case 4:
					return n.getBackgroundColor();
				case 5:
					return n.getText();
				case 6:
					return Arrays.toString(n.getActions());
				case 7:
					return Arrays.toString(n.getInventory());
				}
			}
			return null;
		}

		public void load() {
			inters.clear();
			final RSInterface[] array = RSInterface.getAllInterfaces();
			for (final RSInterface inter : array) {
				final RSInterfaceChild[] children = inter.getChildren();
				for (final RSInterfaceChild child : children) {
					if (child.getText().toLowerCase().contains(
							search.toLowerCase())) {
						;
						inters.add(inter);
						break;
					}
				}
			}
		}

	}

	private JFrame frame;

	private HighlightInterface highlightInterface;

	private InterfaceModel interfaceModel;

	private JTreeTable table;

	public void cleanup() {
		Bot.getEventManager().removeListener(PaintListener.class,
				highlightInterface);
	}

	@Override
	public String getAuthor() {
		return "BAsh";
	}

	@Override
	public String getName() {
		return "Interface Explorer";
	}

	@Override
	public String getScriptCategory() {
		return "Development";
	}

	@Override
	public String getScriptDescription() {
		return "<html>\n"
				+ "<head></head>\n"
				+ "<body>\n"
				+ "<center>"
				+ "<h2>"
				+ getName()
				+ "</h2>"
				+ "</center>\n"
				+ "<p\n"
				+ "<b>Author:</b> "
				+ getAuthor()
				+ "<p>\n"
				+ "<b>Version:</b> "
				+ getVersion()
				+ "<p>\n"
				+ "This script starts a window that allows the interfaces to be examined.\n<p>"
				+ "The main tree of numbers are indexes for the parent interface: "
				+ "RSInterface.getInterface([main]) <br>The subtrees are indexes of the child interfaces: "
				+ "RSInterface.getInterface([main]).getChild([child]) or "
				+ "RSInterface.getChildInterface([main],[child])\n<p>"
				+ "A box is drawn on the main screen indicating where the interface is."
				+ "</body>\n" + "</html>";
	}

	@Override
	public double getVersion() {
		return 2;
	}

	@Override
	public int loop() {
		while (frame.isVisible()) {
			return random(100, 200);
		}
		return -1;
	}

	@Override
	public boolean onStart(final Map<String, String> map) {
		frame = new JFrame(
				"Interface Explorer by BAsh LOL AFTERMATH WAS HERE OMGGGGGG GUN00000T");
		interfaceModel = new InterfaceModel();
		highlightInterface = new HighlightInterface();
		final JButton button = new JButton("Update");
		final JButton search = new JButton("Search...");
		final JButton removeFilters = new JButton("Remove Filters");

		final JPanel buttonPanel = new JPanel(new FlowLayout());
		buttonPanel.add(button);
		buttonPanel.add(search);
		buttonPanel.add(removeFilters);

		final ActionListener al = new ActionListener() {
			JScrollPane scroll;

			public void actionPerformed(final ActionEvent e) {
				interfaceModel.load();
				if (scroll != null) {
					frame.remove(scroll);
				}
				table = new JTreeTable(interfaceModel);
				table.getSelectionModel().addListSelectionListener(
						highlightInterface);
				table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
				scroll = new JScrollPane(table);
				frame.add(scroll, BorderLayout.CENTER);
				frame.pack();
			}
		};

		removeFilters.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				interfaceModel.search = "";
				al.actionPerformed(null);
			}
		});

		search.addActionListener(new ActionListener() {
			public void actionPerformed(final ActionEvent e) {
				final String search = JOptionPane.showInputDialog(frame,
						"Whaddaya wanna search for? :3",
						"Quest for the holy grail!",
						JOptionPane.QUESTION_MESSAGE);
				if (search == null) {
					interfaceModel.search = "";
				} else {
					interfaceModel.search = search;
				}
				al.actionPerformed(null);
			}
		});

		al.actionPerformed(null);
		button.addActionListener(al);
		frame.add(buttonPanel, BorderLayout.SOUTH);

		frame.setResizable(true);
		frame.pack();
		frame.setVisible(true);
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(final WindowEvent e) {
				cleanup();
			}
		});
		return true;
	}
}
